import curses
import time

class ProgressBar:

    def __init__(self, title="", description="", big_description="", value=0, max_value=100, length=20):
        self.title           = title
        self.value           = value
        self.length          = length
        self.description     = description
        self.big_description = big_description
        self.max_value       = max_value

    def increase_progress(self):
        self.value += 1

    def set_progress(self, value):
        self.value = value

    def value_to_percentage(self):
        return int(float(self.value) / float(self.max_value) * 100)

    def percentage_to_string(self):
        return f"({self.value_to_percentage()}%)"
    
    def get_progress_string(self):
        progress_string = ""
        percent_value = self.value_to_percentage()

        delim = (10 / (self.length * 0.1))
        for i in range(1, self.length+1):
            if i*delim <= percent_value: progress_string += "="
            elif delim*i-percent_value <= delim: progress_string += ">"
            else: progress_string += "."

        return f"[{progress_string}]"

    def get_progress_part(self):
        progress = self.get_progress_string()
        dote_index = progress.find(".")
        return progress[:dote_index]

    def get_unprogress_part(self):
        progress = self.get_progress_string()
        dote_index = progress.find(".")
        return progress[dote_index:]

    def draw(self, screen):
        screen.erase()
        
        max_y, max_x = screen.getmaxyx()
        middle_y, middle_x = int(max_y/2), int(max_x/2)

        #========== Title string ==========#
        title_string = self.title
        title_padding = int(len(title_string) / 2)

        #========== Progress string ==========#
        progress_string = self.get_progress_string()
        progress_padding = int(len(progress_string) / 2)

        ppart = self.get_progress_part()
        upart = self.get_unprogress_part()

        #========== Description string ==========#
        description_string = self.description + " " + self.percentage_to_string()
        description_padding = int(len(description_string) / 2)

        #==========> Big Description string <==========#
        bd_string = self.big_description 
        bd_padding = int(len(bd_string)/2)
    
        #==========> Print strings <==========#
        screen.attron(curses.A_BOLD)
        screen.addstr(middle_y-4, middle_x-title_padding, title_string, self.BLUE_TEXT)
        screen.attroff(curses.A_BOLD)

        screen.attron(curses.A_ITALIC)
        screen.addstr(middle_y-2, middle_x-description_padding, description_string)
        screen.addstr(middle_y, middle_x-bd_padding, bd_string)
        screen.attroff(curses.A_ITALIC)

        screen.addstr(middle_y+2, middle_x-progress_padding, ppart, self.GREEN_TEXT)
        screen.addstr(middle_y+2, middle_x-progress_padding+len(ppart), upart[:-1])
        screen.addstr(middle_y+2, middle_x-progress_padding+len(ppart)+len(upart)-1, upart[-1], self.GREEN_TEXT)

        screen.refresh()
    
    def exit(self):
        self.value = self.max_value

    def loop(self, screen):
        while self.value < self.max_value: self.draw(screen)

    def init_curses(self):
        curses.use_default_colors()
        
        curses.init_pair(1, curses.COLOR_GREEN, -1)
        self.GREEN_TEXT = curses.color_pair(1)

        curses.init_pair(2, curses.COLOR_BLUE, -1)
        self.BLUE_TEXT = curses.color_pair(2)

        curses.init_pair(3, curses.COLOR_CYAN, -1)
        self.CYAN_TEXT = curses.color_pair(3)

        curses.curs_set(0)
        curses.initscr()

    def _start(self, screen):
        self.init_curses()
        screen.idlok(False)
        screen.idcok(False)
        return self.loop(screen)

    def start_loop(self):
        return curses.wrapper(self._start)

def start(title="", description="", value=0, max_value=100, length=20):
    pb = ProgressBar(title, description, value, max_value, length)
    pb.start_loop()

if __name__ == "__main__":
    pb = ProgressBar("test of bar", "loliconshik3", 95, 100, 20)
    pb.start_loop()


